#include "MP3Header.h"

const uint32 CMP3Header::frequencies[2][4] = { {22050, 24000, 16000, 1}, {44100, 48000, 32000, 1} };

bool CMP3Header::read_header(CBitStream *stream)
{
	uint32 headerstring, channel_bitrate;

	if (!initial_sync)
	{
		if (!stream->get_header(&headerstring,INITIAL_SYNC))
			return false;

		h_version = (e_version)((headerstring >> 19) & 1);
		if ((h_sample_frequency = (e_sample_frequency)((headerstring >> 10) & 3)) == 3)
			return false;

		stream->set_syncword(headerstring & 0xFFF80CC0);
		initial_sync = true;
	}
	else
	{
		if (!stream->get_header(&headerstring, STRICT_SYNC))
			return false;
	}

	h_layer = 4 - (headerstring >> 17) & 3;
	h_protection_bit = (headerstring >> 16) & 1;
	h_bitrate_index  = (headerstring >> 12) & 0xF;
	h_padding_bit = (headerstring >> 9) & 1;
	h_mode        = (e_mode)((headerstring >> 6) & 3);
	h_mode_extension = (headerstring >> 4) & 3;

	if (h_mode == joint_stereo)
		h_intensity_stereo_bound = (h_mode_extension << 2) + 4;
	else
		h_intensity_stereo_bound = 0;		// should never be used

	h_copyright = (bool)((headerstring >> 3) & 1);
	h_original  = (bool)((headerstring >> 2) & 1);

	// calculate number of subbands:
	channel_bitrate = h_bitrate_index;

	// calculate bitrate per channel:
	if (h_mode != single_channel)
		if (channel_bitrate == 4)
			channel_bitrate = 1;
		else
			channel_bitrate -= 4;

	if ((channel_bitrate == 1) || (channel_bitrate == 2))
		if (h_sample_frequency == thirtytwo)
			h_number_of_subbands = 12;
		else
			h_number_of_subbands = 8;
	else
		if ((h_sample_frequency == fourtyeight) || ((channel_bitrate >= 3) && (channel_bitrate <= 5)))
			h_number_of_subbands = 27;
		else
			h_number_of_subbands = 30;

	if (h_intensity_stereo_bound > h_number_of_subbands)
		h_intensity_stereo_bound = h_number_of_subbands;


	// calculate framesize and nSlots
	calculate_framesize();

	// read framedata:
	if (stream->read_frame(framesize) == false)
		return false;

	if (!h_protection_bit)
	{
		// frame contains a crc checksum
		checksum = (uint16) stream->get_bits(16);
	}

	return true;
}

// calculates framesize in bytes excluding header size
uint32 CMP3Header::calculate_framesize()
{
	static const int32 bitrates[2][3][16] =
	{
		{{0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000 ,224000, 256000, 0},
		 {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0},
		 {0 /*free format*/, 8000, 16000, 24000, 32000, 40000, 48000,56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 0}},

		{{0 /*free format*/, 32000, 64000, 96000, 128000, 160000, 192000,224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000, 0},
		 {0 /*free format*/, 32000, 48000, 56000, 64000, 80000, 96000,112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000, 0},
		 {0 /*free format*/, 32000, 40000, 48000, 56000, 64000, 80000,96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 0}}
	};

	framesize = (144 * bitrates[h_version][h_layer - 1][h_bitrate_index]) / frequencies[h_version][h_sample_frequency];

	if (h_version == MPEG2_LSF)
    	framesize >>= 1;
	if (h_padding_bit)
		framesize++;

	if (h_version == MPEG1)
		nSlots = framesize - ((h_mode == single_channel) ? 17 : 32)	// side info size
								-  (h_protection_bit ? 0 : 2) 		// CRC size
								- 4; 								// header size
	else
        nSlots = framesize - ((h_mode == single_channel) ?  9 : 17)	// side info size
						   	-  (h_protection_bit ? 0 : 2) 		    // CRC size
								- 4; 								// header size

	// subtract header size  
	framesize -= 4;
	return framesize;
}
